package com.tanhua.dubbo.api;

import cn.hutool.core.collection.CollectionUtil;
import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable;
import com.tanhua.MongoAppilcation;
import com.tanhua.dubbo.service.TimeLineService;
import com.tanhua.dubbo.utils.Idworker;
import com.tanhua.model.mongo.Friend;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.MovementTimeLine;
import com.tanhua.model.vo.PageResultVo;
import org.apache.dubbo.config.annotation.DubboService;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;


import java.util.List;

/**
 * @Description: test
 * @Create by: JJ菜菜
 * @Date: 2021/12/1 23:48
 */
@DubboService
public class MovementApiImpl implements MovementApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private Idworker idworker;

    @Autowired
    private TimeLineService timeLineService;

    /**
     * 发布动态
     * @param movement
     */
    @Override
    public void publish(Movement movement) {

        // 设置时间和pid进行动态的保存
        movement.setPid(idworker.getNextId("movement"));
        movement.setCreated(System.currentTimeMillis());
        mongoTemplate.save(movement);

        // 调用抽取的异步添加好友时间线方法。
        timeLineService.saveTimeLine(movement);
    }

    /**
     * 查询个人动态
     * @param page
     * @param pageSize
     * @param userId
     * @return
     */
    @Override
    public PageResultVo findMovement(int page, int pageSize, Long userId) {

        // 构建mongo所需要的条件
        Criteria criteria = Criteria.where("userId").is(userId);
        Query query = Query.query(criteria)
                .skip((page - 1) * pageSize)
                .limit(pageSize)
                .with(Sort.by(Sort.Order.desc("created")));
        Integer count = Math.toIntExact(mongoTemplate.count(query, Movement.class));
        List<Movement> movements = mongoTemplate.find(query, Movement.class);
        // 封装数据进行返回
        PageResultVo vo = new PageResultVo(page, pageSize, count, movements);
        return vo;
    }

    /**
     * 查询好友动态
     * @param page
     * @param pageSize
     * @param userId
     * @return
     *
     *  好友时间线---(userId)--> movement
     */
    @Override
    public List<Movement> friendMovement(Integer page, Integer pageSize, Long userId) {

        // 先查询好友时间线表
        Criteria criteria = Criteria.where("friendId").is(userId);
        Query query = Query.query(criteria)
                .skip((page - 1) * pageSize)
                .limit(pageSize)
                .with(Sort.by(Sort.Order.desc("created")));
        List<MovementTimeLine> movementTimeLines = mongoTemplate.find(query, MovementTimeLine.class);

        // 使用hutool工具提取movementId
        List<ObjectId> movementId = CollectionUtil.getFieldValues(movementTimeLines, "movementId", ObjectId.class);
        // 查询movement表
        Query movementQuery = Query.query(Criteria.where("id").in(movementId));
        List<Movement> movementList = mongoTemplate.find(movementQuery, Movement.class);
        return movementList;
    }

    /**
     * 随机查询动态
     * @param pageSize
     * @return
     */
    @Override
    public List<Movement> randomMovements(Integer pageSize, Long userId) {

        // 随机查询方法， 百度
        Aggregation agg = Aggregation.newAggregation(
                Aggregation.match(Criteria.where("userId").ne(userId)), // 排除
                Aggregation.sample(pageSize)
        );
        // 查询
        AggregationResults<Movement> results = mongoTemplate.aggregate(agg, Movement.class, Movement.class);
        List<Movement> movements = results.getMappedResults();
        return movements;
    }

    /**
     * 根据pid查询动态
     * @param pids
     * @return
     */
    @Override
    public List<Movement> findMovementByPid(List<Long> pids) {


        Criteria criteria = Criteria.where("pid").in(pids);
        Query query = Query.query(criteria)
                .with(Sort.by(Sort.Order.desc("created")));
        List<Movement> movementList = mongoTemplate.find(query, Movement.class);
        return movementList;
    }

    /**
     * 单条动态查询
     * @param movementId
     * @return
     */
    @Override
    public Movement findById(String movementId) {
        return mongoTemplate.findById(movementId,Movement.class);
    }

    @Override
    public PageResultVo findByUserId(Long uid, Integer state, Integer page, Integer pagesize) {

        Query query = new Query();
        if(uid != null) {
            query.addCriteria(Criteria.where("userId").is(uid));
        }
        if(state != null) {
            query.addCriteria(Criteria.where("state").is(state));
        }
        //查询总数
        long count = mongoTemplate.count(query, Movement.class);
        //设置分页参数
        query.with(Sort.by(Sort.Order.desc("created"))).limit(pagesize).skip((page -1) * pagesize);

        List<Movement> list = mongoTemplate.find(query, Movement.class);
        return new PageResultVo(page,pagesize, (int) count,list);
    }

    @Override
    public void update(String movementId, Integer state) {
        Query query = Query.query(Criteria.where("id").in(new ObjectId(movementId)));
        Update update = Update.update("state", state);
        mongoTemplate.updateFirst(query, update, Movement.class);
    }


}
